package ma.wafaassurance.ged.service.icm;

import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import ma.wafaassurance.ged.datatype.DocumentHandler;
import ma.wafaassurance.ged.datatype.Famille;
import ma.wafaassurance.ged.datatype.Index;
import ma.wafaassurance.ged.datatype.PartDocumentHandler;
import ma.wafaassurance.ged.service.GedService;

import com.caucho.hessian.server.HessianServlet;
import com.ibm.mm.sdk.common.DKConstant;
import com.ibm.mm.sdk.common.DKConstantICM;
import com.ibm.mm.sdk.common.DKDDO;
import com.ibm.mm.sdk.common.DKException;
import com.ibm.mm.sdk.common.DKLobICM;
import com.ibm.mm.sdk.common.DKParts;
import com.ibm.mm.sdk.common.DKResults;
import com.ibm.mm.sdk.common.DKRetrieveOptionsICM;
import com.ibm.mm.sdk.common.DKUsageError;
import com.ibm.mm.sdk.common.dkIterator;
import com.ibm.mm.sdk.server.DKDatastoreICM;

public class GedServiceImpl extends HessianServlet implements GedService {
    
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String database;
    private String userName;
    private String password;
    private String schema;
    // private String famille;
    private DateFormat dateAnnee = new SimpleDateFormat("yyyy");
    private DateFormat dateMois = new SimpleDateFormat("MM");
    private DateFormat dateJour = new SimpleDateFormat("dd");
    
    @Override
    public List<DocumentHandler> listerDocumentGEDParStatut(String statut, String famille) {
        List<DocumentHandler> documentHandlers = new ArrayList<DocumentHandler>();
        
        DKResults pResults = null;
        construireParametreConection();
        DKParts parts = null;
        try {
            String query = "/" + famille + "[@" + Index.Statut + "= \"" + statut + "\"]";
            // String query = "/CNSS[@numcont= 56993]";
            DKDatastoreICM dsICM = new DKDatastoreICM();
            dsICM.connect(database, userName, password, schema);
            pResults = (DKResults) dsICM.evaluate(query, DKConstantICM.DK_CM_XQPE_QL_TYPE, null);
            DKDDO item = null;
            dkIterator iter = pResults.createIterator();
            System.out.println(" number of items " + pResults.cardinality());
            if (pResults.cardinality() == 0) {
                System.out.println(" résultat de la recherche = null ");
            } else {
                while (iter.more()) {
                    item = (DKDDO) iter.next();
                    
                    DocumentHandler documentHandler = new DocumentHandler();
                    DKRetrieveOptionsICM retrOpts = DKRetrieveOptionsICM.createInstance(dsICM);
                    retrOpts.baseAttributes(true); // Get Base Attributes
                    retrOpts.partsList(true); // Get the parts
                    retrOpts.resourceContent(true); // Get the document content
                    item.retrieve(retrOpts.dkNVPair());
                    
                    short dataID = item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, DKConstant.DK_CM_DKPARTS);
                    if (dataID != 0) { //   
                        parts = (DKParts) item.getData(dataID);
                    } else {
                        throw new Exception("The document parts not found ");
                    }
                    if (parts != null)
                        System.out.println(" this document has " + parts.cardinality() + " parts ");
                    dkIterator it = parts.createIterator();
                    DKLobICM dk;
                    
                    while (it.more()) {
                        dk = (DKLobICM) it.next();
                        dk.getCreatedTimestamp();
                        if (dk != null) {
                            documentHandler.getDocumentParts().add(
                                    new PartDocumentHandler(dk.getContent(), dk.size(), ((DKLobICM) dk).getMimeType()));
                        }
                    }
                    documentHandlers.add(recupererIndex(documentHandler, item));
                    
                }
            }
            dsICM.disconnect();
          
        } catch (DKException exc) {
            exc.printStackTrace();
        } catch (Exception exc) {
            exc.printStackTrace();
        }
        return documentHandlers;
    }
    
    @Override
    public List<DocumentHandler> recupererDocumentGED(DocumentHandler documentHandler, String famille) throws Exception {
        List<DocumentHandler> documentHandlers = new ArrayList<DocumentHandler>();
        DKResults pResults = null;
        construireParametreConection();
        DKParts parts = null;
        
        String query = construireQuery(documentHandler, famille);
        DKDatastoreICM dsICM = new DKDatastoreICM();
        dsICM.connect(database, userName, password, schema);
        pResults = (DKResults) dsICM.evaluate(query, DKConstantICM.DK_CM_XQPE_QL_TYPE, null);
        DKDDO item = null;
        dkIterator iter = pResults.createIterator();
        System.out.println(" number of items " + pResults.cardinality());
        if (pResults.cardinality() == 0) {
            System.out.println(" résultat de la recherche = null ");
        } else {
            while (iter.more()) {
                item = (DKDDO) iter.next();
                DocumentHandler documentHandlernew = new DocumentHandler();
                DKRetrieveOptionsICM retrOpts = DKRetrieveOptionsICM.createInstance(dsICM);
                retrOpts.baseAttributes(true); // Get Base Attributes
                retrOpts.partsList(true); // Get the parts
                retrOpts.resourceContent(true); // Get the document content
                item.retrieve(retrOpts.dkNVPair());
                short dataID = item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, DKConstant.DK_CM_DKPARTS);
                if (dataID != 0) { //   
                    parts = (DKParts) item.getData(dataID);
                } else {
                    throw new Exception("The document parts not found ");
                }
                if (parts != null)
                    System.out.println(" this document has " + parts.cardinality() + " parts ");
                dkIterator it = parts.createIterator();
                DKLobICM dk;
                
                while (it.more()) {
                    dk = (DKLobICM) it.next();
                    dk.getCreatedTimestamp();
                    if (dk != null) {
                        documentHandlernew.getDocumentParts().add(
                                new PartDocumentHandler(dk.getContent(), dk.size(), ((DKLobICM) dk).getMimeType()));
                    }
                }
                
                documentHandlers.add(recupererIndex(documentHandlernew, item));
            }
        }
        dsICM.disconnect();
        return documentHandlers;
    }
    
    @Override
    public DocumentHandler modifierIndexDocumentGED(DocumentHandler documentHandlerNouveau) throws Exception {
        String pidString = documentHandlerNouveau.getpId();
        if (pidString == null || pidString.trim().length() == 0) {
            throw new Exception("PID string is null - nothing to retrieve.");
        }
        construireParametreConection();
        try {
            DKDatastoreICM dsICM = new DKDatastoreICM();
            dsICM.connect(database, userName, password, schema);
            DKDDO ddo = dsICM.createDDOFromPID(pidString);
            DKRetrieveOptionsICM retrOpts = DKRetrieveOptionsICM.createInstance(dsICM);
            retrOpts.baseAttributes(true); // Get Base Attributes
            retrOpts.partsList(true); // Get the parts
            retrOpts.resourceContent(true); // Get the document content
            ddo.retrieve(retrOpts.dkNVPair());
            modifierIndex(documentHandlerNouveau, ddo);
            try {
                dsICM.checkOut(ddo);
                ddo.update(DKConstant.DK_CM_CHECKIN);
            } catch (Exception expec) {
                dsICM.checkIn(ddo);
                dsICM.checkOut(ddo);
                ddo.update(DKConstant.DK_CM_CHECKIN);
            }
            dsICM.disconnect();
        } catch (DKException exc) {
            exc.printStackTrace();
        } catch (Exception exc) {
            exc.printStackTrace();
        }
        return documentHandlerNouveau;
    }
    
    @Override
    public DocumentHandler recupererDocumentParPid(String pidString) throws Exception {
        if (pidString == null || pidString.trim().length() == 0) {
            throw new Exception("PID string is null - nothing to retrieve.");
        }
        construireParametreConection();
        DKDatastoreICM dsICM = new DKDatastoreICM();
        dsICM.connect(database, userName, password, schema);
        DKDDO ddo = dsICM.createDDOFromPID(pidString);
        DocumentHandler documentHandler = new DocumentHandler();
        DKRetrieveOptionsICM retrOpts = DKRetrieveOptionsICM.createInstance(dsICM);
        retrOpts.baseAttributes(true); // Get Base Attributes
        retrOpts.partsList(true); // Get the parts
        retrOpts.resourceContent(true); // Get the document content
        ddo.retrieve(retrOpts.dkNVPair());
        DKParts parts = null;
        short dataID = ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, DKConstant.DK_CM_DKPARTS);
        if (dataID != 0) { //   
            parts = (DKParts) ddo.getData(dataID);
        } else {
            throw new Exception("The document parts not found for pid: " + pidString);
        }
        DKLobICM dk = null;
        if (parts != null) {
            dkIterator iter = (dkIterator) parts.createIterator();
            while (iter.more()) {
                DKDDO d = (DKDDO) iter.next();
                if (d instanceof DKLobICM) {
                    dk = (DKLobICM) d;
                    documentHandler.getDocumentParts().add(
                            new PartDocumentHandler(dk.getContent(), dk.size(), ((DKLobICM) dk).getMimeType()));
                }
            }
        }
        return recupererIndex(documentHandler, ddo);
    }
    
    // private DocumentHandler recupererIndex1(DocumentHandler documentHandler,
    // DKDDO item) throws DKUsageError {
    // documentHandler.setNumPolice((Integer)
    // item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
    // Index.Npolice.toString())));
    // documentHandler.setCategorie((Integer)
    // item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
    // Index.Categorie.toString())));
    // documentHandler.setExercice((Integer)
    // item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
    // Index.Exercice.toString())));
    // documentHandler.setMois((String)
    // item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
    // Index.Mois.toString())));
    //        
    // documentHandler.setpId(item.getPidObject().pidString());
    // return documentHandler;
    // }
    //    
    private DocumentHandler recupererIndex(DocumentHandler documentHandler, DKDDO item) throws DKUsageError {
        if (item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.NomDocument.toString()) != 0) {
            documentHandler.setNomDocument((String) item
                    .getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.NomDocument.toString())));
        } else {
            documentHandler.setNumPolice((Integer) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.numcont.toString())));
            documentHandler.setCategorie((Integer) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.cat.toString())));
            documentHandler.setExercice((Integer) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.exe.toString())));
            documentHandler.setMois((Integer) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.moiss.toString())));
            documentHandler.setNumClient((Integer) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.numclient.toString())));
            documentHandler
                    .setNumAffiliation((Integer) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.numaff.toString())));
            documentHandler.setDateEnregistrement((Date) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.dateinsert
                    .toString())));
            documentHandler.setMineType((String) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.minetype.toString())));
            
            documentHandler.setNumDocument((String) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.Ndocument.toString())));
            documentHandler.setStatut((String) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.Statut.toString())));
            documentHandler.setDateCachet((Date) item.getData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.DateCachet.toString())));
            
        }
        documentHandler.setpId(item.getPidObject().pidString());
        return documentHandler;
    }
    
    private void modifierIndex(DocumentHandler documentHandler, DKDDO item) throws DKUsageError {
        if (item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.NomDocument.toString()) != 0) {
            item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.NomDocument.toString()), documentHandler.getNomDocument());
        } else {
            if (documentHandler.getNumPolice() != null) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.numcont.toString()), documentHandler.getNumPolice());
            }
            if (documentHandler.getCategorie() != null) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.cat.toString()), documentHandler.getCategorie());
            }
            
            if (documentHandler.getExercice() != null) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.exe.toString()), documentHandler.getExercice());
            }
            if (documentHandler.getMois() != null) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.moiss.toString()), documentHandler.getMois());
            }
            if (documentHandler.getNumClient() != null) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.numclient.toString()), documentHandler.getNumClient());
            }
            if (documentHandler.getNumAffiliation() != null) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.numaff.toString()), documentHandler.getNumAffiliation());
            }
            if (documentHandler.getDateEnregistrement() != null) {
                java.sql.Date dateEnregistrement = new java.sql.Date(documentHandler.getDateEnregistrement().getTime());
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.dateinsert.toString()), dateEnregistrement);
            }
            if (documentHandler.getMineType() != null) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.minetype.toString()), documentHandler.getMineType());
            }
            if (documentHandler.getNumDocument() != null && !documentHandler.getNumDocument().trim().equals("")) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.Ndocument.toString()), documentHandler.getNumDocument());
            }
            if (documentHandler.getStatut() != null && !documentHandler.getStatut().equals("")) {
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.Statut.toString()), documentHandler.getStatut());
            }
            if (documentHandler.getDateCachet() != null) {
                java.sql.Date dateCachet = new java.sql.Date(documentHandler.getDateCachet().getTime());
                item.setData(item.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, Index.DateCachet.toString()), dateCachet);
            }
        }
        
    }
    
    private String construireQuery(DocumentHandler documentHandler, String famille) {
        String query;
        query = "/" + famille + "[1=1";
        if (Famille.WASSIL.toString().equals(famille)) {
            query = concatQuery(query, Index.NomDocument, getFormatString(documentHandler.getNomDocument()));
        } else {
            query = concatQuery(query, Index.numcont, getFormatString(documentHandler.getNumPolice()));
            query = concatQuery(query, Index.cat, getFormatString(documentHandler.getCategorie()));
            query = concatQuery(query, Index.exe, getFormatString(documentHandler.getExercice()));
            query = concatQuery(query, Index.moiss, getFormatString(documentHandler.getMois()));
            query = concatQuery(query, Index.numclient, getFormatString(documentHandler.getNumClient()));
            query = concatQuery(query, Index.numaff, getFormatString(documentHandler.getNumAffiliation()));
            query = concatQuery(query, Index.dateinsert, getFormatDate(documentHandler.getDateEnregistrement()));
            query = concatQuery(query, Index.minetype, documentHandler.getMineType());
            query = concatQuery(query, Index.Ndocument, documentHandler.getNumDocument());
            query = concatQuery(query, Index.DateCachet, getFormatDate(documentHandler.getDateCachet()));
            query = concatQuery(query, Index.Statut, documentHandler.getStatut());
        }
        query = query + "]";
        return query;
    }
    
    private String concatQuery(String query, Index index, String valeurIndex) {
        return query + ((valeurIndex != null && !"".equals(valeurIndex)) ? (" and @" + index + "=\"" + valeurIndex + "\"") : "");
    }
    
    private String getFormatDate(Date date) {
        return date != null ? dateAnnee.format(date) + "/" + dateMois.format(date) + "/" + dateJour.format(date) : "";
    }
    
    private String getFormatString(Object object) {
        return object != null ? object.toString() : "";
    }
    
    @Override
    public String ajouterDocument(DocumentHandler documentHandler, String famille) {
        construireParametreConection();
        String documentPId = null;
        // String filePath = "C://Users//r.ourgani//Desktop//Ref.txt";
        try {
            DKDatastoreICM dsICM = new DKDatastoreICM();
            dsICM.connect(database, userName, password, schema);
            DKDDO document = dsICM.createDDO(famille, DKConstant.DK_CM_DOCUMENT);
            DKLobICM base = (DKLobICM) dsICM.createDDO("ICMBASE", DKConstant.DK_CM_ITEM);
            modifierIndex(documentHandler, document);
            DKParts dkParts = (DKParts) document.getData(document.dataId(DKConstant.DK_CM_NAMESPACE_ATTR, DKConstant.DK_CM_DKPARTS));
            // Store the File
            // if (filePath != null && !"".equals(filePath.trim())) {
            // base.setContentFromClientFile(filePath);
            // } else {
            base.setContent(documentHandler.getDocumentParts().get(0).getContent());
            // }
            base.setMimeType(documentHandler.getDocumentParts().get(0).getContentType());
            dkParts.addElement(base);
            document.add();
            documentPId = document.getPidObject().toString();
            dsICM.disconnect();
            
        } catch (DKException exc) {
            exc.printStackTrace();
        } catch (Exception exc) {
            exc.printStackTrace();
        }
        return documentPId;
    }
    
    private void construireParametreConection() {
        Properties specificationEcranProperties = new Properties();
        try {
            specificationEcranProperties.load(getClass().getResourceAsStream("/config.properties"));
            database = specificationEcranProperties.getProperty("database");
            userName = specificationEcranProperties.getProperty("userName");
            password = specificationEcranProperties.getProperty("password");
            schema = specificationEcranProperties.getProperty("schema");
            // famille = specificationEcranProperties.getProperty("famille");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
}
